package org.example.servlet;

import com.alibaba.fastjson.JSON;
import org.example.other.ErrorEnum;
import org.example.other.ServiceException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * 自定义BaseServlet父类,继承HttpServlet
 * 内部有抽象方法需要子类继承和实现, 因此定义为抽象类
 */
public abstract class BaseServlet extends HttpServlet {
    /**
     * 封装一个把对象转换为json格式字符串进行响应的方法
     * 此方法可被所有Servlet子类继承复用
     * @param response 响应对象
     * @param data 要响应给前端的数据对象
     * @throws IOException
     */
    public void responseObjectToJson (HttpServletResponse response, Object data) throws IOException {
        // 1. 设置响应头: 告诉前端响应内容的类型是json格式,字符集是utf-8
        response.setContentType("application/json;charset=utf-8");
        // 2. 获取输出流
        PrintWriter out = response.getWriter();
        // 3. 将对象data转为json格式后输出
        out.write(JSON.toJSONString(data));
        // 4. 冲刷流,防止流不自动冲刷
        out.flush();
        // 5. 关闭流
        out.close();
    }

    /**
     * 封装默认的成功响应方法
     * @param response
     * @throws IOException
     */
    public void success(HttpServletResponse response) throws IOException {
        Map map = new HashMap();
        map.put("code", ErrorEnum.SUCCESS.getCode());
        map.put("message", ErrorEnum.SUCCESS.getMessage());
        responseObjectToJson(response, map);
    }
    /**
     * 封装返回数据的成功响应方法
     * @param response
     * @param data
     * @throws IOException
     */
    public void success(HttpServletResponse response, Object data) throws IOException {
        Map map = new HashMap();
        map.put("code", ErrorEnum.SUCCESS.getCode());
        map.put("message", ErrorEnum.SUCCESS.getMessage());
        map.put("data", data);
        responseObjectToJson(response, map);
    }

    /**
     * 封装返回错误码和错误信息的响应方法
     * @param response
     * @param errorEnum
     * @throws IOException
     */
    public void error(HttpServletResponse response, ErrorEnum errorEnum) throws IOException {
        Map map = new HashMap();
        map.put("code", errorEnum.getCode());
        map.put("message", errorEnum.getMessage());
        responseObjectToJson(response, map);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            handleRequest(req,resp);
        } catch (Exception e) {
            // 打印异常追踪栈在控制台, 给程序员自己看
            e.printStackTrace();
            // 响应异常信息给前端, 展示给用户看
            if (e instanceof ServiceException) {
                ErrorEnum errorEnum = ((ServiceException) e).getErrorEnum();
                error(resp, errorEnum);
            } else {
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "服务器异常");
            }
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            handleRequest(req,resp);
        } catch (Exception e) {
            // 打印异常追踪栈在控制台, 给程序员自己看
            e.printStackTrace();
            // 响应异常信息给前端, 展示给用户看
            if (e instanceof ServiceException) {
                ErrorEnum errorEnum = ((ServiceException) e).getErrorEnum();
                error(resp, errorEnum);
            } else {
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "服务器异常");
            }
        }
    }

    public Integer getIntegerParameter(HttpServletRequest request, String parameterName) {
        String parameter = request.getParameter(parameterName);
        if (parameter == null) {
            return null;
        }
        return Integer.parseInt(parameter);
    }

    public Double getDoubleParameter(HttpServletRequest request, String parameterName) {
        String parameter = request.getParameter(parameterName);
        if (parameter == null) {
            return null;
        }
        return Double.parseDouble(parameter);
    }

    protected abstract void handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception;
}
